// 并集集 - 解决网格风暴连通分量问题
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

// 自定义并查集类 - 用于管理连通分量
struct DSU {
  vector<int> parent, size; // parent数组存储父节点，size数组存储集合大小

  // 构造函数：初始化n个独立的集合
  DSU(int n) {
    parent.resize(n);
    size.resize(n, 1); // 每个集合初始大小为1
    for (int i = 0; i < n; i++)
      parent[i] = i; // 每个元素初始时指向自己
  }

  // 查找元素x所在集合的代表元素（路径压缩优化）
  int find(int x) {
    if (parent[x] == x)
      return x;
    return parent[x] = find(parent[x]); // 路径压缩
  }

  // 判断两个元素是否属于同一集合
  bool same(int x, int y) { return find(x) == find(y); }

  // 合并两个元素所在的集合（按秩合并优化）
  void merge(int x, int y) {
    int rootx = find(x);
    int rooty = find(y);
    if (rootx == rooty)
      return; // 已经在同一集合中
    if (size[rootx] < size[rooty])
      swap(rootx, rooty);  // 保证x的集合更大
    parent[rooty] = rootx; // 将较小的集合合并到较大的集合
    size[rootx] += size[rooty];
  }

  // 获取元素x所在集合的大小
  int get_size(int x) { return size[find(x)]; }
};

// 矩形结构体 - 表示网格中的一个矩形区域
struct Rect {
  ll lx, rx, ly, ry; // 左边界、右边界、下边界、上边界（左闭右开区间）
};

int main() {
  // 输入处理：n次风暴，网格大小为x×y
  int n, x, y;
  cin >> n >> x >> y;

  // 初始化：整个网格作为一个矩形
  vector<Rect> rects;
  rects.emplace_back(0, x, 0, y);
  // 初始矩形覆盖整个网格 (0, x, 0, y) 表示 [0, x) × [0, y) 的区域

  // 处理每次风暴
  for (int i = 0; i < n; i++) {
    vector<Rect> old;
    swap(rects, old); // 保存当前矩形集合，准备处理新风暴

    char c;   // 风暴类型：'X'或'Y'
    int a, b; // 风暴参数：分界线a，偏移量b
    cin >> c >> a >> b;

    // 对每个现有矩形进行风暴变换
    for (Rect e : old) {
      if (c == 'X') {
        // X型风暴：根据x坐标与a的关系进行变换
        if (e.lx < a and a < e.rx) {
          // 情况1：分界线a穿过矩形内部，需要分割
          // 左半部分：x < a，y坐标减去b
          rects.emplace_back(e.lx, a, e.ly - b, e.ry - b);
          // 右半部分：x ≥ a，y坐标加上b
          rects.emplace_back(a, e.rx, e.ly + b, e.ry + b);
        } else if (e.rx <= a) {
          // 情况2：整个矩形在分界线左侧，y坐标减去b
          rects.emplace_back(e.lx, e.rx, e.ly - b, e.ry - b);
        } else {
          // 情况3：整个矩形在分界线右侧，y坐标加上b
          rects.emplace_back(e.lx, e.rx, e.ly + b, e.ry + b);
        }
      } else {
        // Y型风暴：根据y坐标与a的关系进行变换
        if (e.ly < a and a < e.ry) {
          // 情况1：分界线a穿过矩形内部，需要分割
          // 下半部分：y < a，x坐标减去b
          rects.emplace_back(e.lx - b, e.rx - b, e.ly, a);
          // 上半部分：y ≥ a，x坐标加上b
          rects.emplace_back(e.lx + b, e.rx + b, a, e.ry);
        } else if (e.ry <= a) {
          // 情况2：整个矩形在分界线下方，x坐标减去b
          rects.emplace_back(e.lx - b, e.rx - b, e.ly, e.ry);
        } else {
          // 情况3：整个矩形在分界线上方，x坐标加上b
          rects.emplace_back(e.lx + b, e.rx + b, e.ly, e.ry);
        }
      }
    }
  }

  // 风暴处理完成，现在rects包含所有最终的矩形区域
  int m = rects.size();

  // 使用并查集合并相邻的矩形
  DSU uf(m);
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < i; j++) {
      Rect a = rects[i];
      Rect b = rects[j];

      // 计算两个矩形在x轴和y轴上的重叠长度
      ll cx = min(a.rx, b.rx) - max(a.lx, b.lx); // x轴重叠长度
      ll cy = min(a.ry, b.ry) - max(a.ly, b.ly); // y轴重叠长度

      if (cx < 0 || cy < 0)
        continue; // 没有重叠

      // 如果有重叠（面积大于0），则合并这两个矩形
      if (cx ||  cy)
        uf.merge(i, j);
    }
  }

  // 计算每个连通分量的总面积
  vector<ll> areas(m, 0); // 初始化面积数组
  for (int i = 0; i < m; i++) {
    Rect a = rects[i];
    // 将当前矩形的面积加到其连通分量的总面积中
    areas[uf.find(i)] += (a.rx - a.lx) * (a.ry - a.ly);
  }

  // 处理面积数组：排序并去除零面积

  vector<ll> result;
  for (ll area : areas) {
    if (area > 0) {
      result.push_back(area); // O(1) 摊销时间
    }
  }
  sort(result.begin(), result.end()); // 只对非零元素排序

  // 输出结果
  cout << result.size() << '\n'; // 连通分量数量
  for (ll a : result)
    cout << a << ' '; // 每个连通分量的面积（升序）

  return 0;
}